﻿/*
 * ©2009-2010 XELF
 * http://xelf.info
 */

namespace XELF.Framework {

	public partial struct Vector3 {
		/// <summary>
		/// 変換したベクトルを得る。クォータニオンが回転クォータニオンであれば、回転したベクトルを得る。
		/// 多くの点を変換するときには、クォータニオンを行列に変換して対応するメソッドを使うと良い。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="rotation"></param>
		/// <param name="result"></param>
		public static void Transform(ref Vector3 position, ref Quaternion rotation, out Vector3 result) {
			Quaternion q = new Quaternion(position.X, position.Y, position.Z, 0);
			Quaternion inverse;
			Quaternion.Invert(ref rotation, out inverse);
			Quaternion.Multiply(ref rotation, ref q, out q);
			Quaternion.Multiply(ref q, ref inverse, out q);
			result.X = q.X;
			result.Y = q.Y;
			result.Z = q.Z;
		}
	}

	public partial struct Vector2 {
		/// <summary>
		/// 変換する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <param name="result"></param>
		public static void Transform(ref Vector2 position, ref Matrix matrix, out Vector2 result) {
			result = new Vector2(
				position.X * matrix.M11 + position.Y * matrix.M31 + matrix.M41,
				position.X * matrix.M12 + position.Y * matrix.M32 + matrix.M42);
		}
		/// <summary>
		/// 変換する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <returns></returns>
		public static Vector2 Transform(Vector2 position, Matrix matrix) {
			Vector2 result;
			Transform(ref position, ref matrix, out result);
			return result;
		}
	}

	public partial struct Vector3 {
		/// <summary>
		/// 変換する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <param name="result"></param>
		public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector3 result) {
			result = new Vector3(
				position.X * matrix.M11 + position.Y * matrix.M21 + position.Z * matrix.M31 + matrix.M41,
				position.X * matrix.M12 + position.Y * matrix.M22 + position.Z * matrix.M32 + matrix.M42,
				position.X * matrix.M13 + position.Y * matrix.M23 + position.Z * matrix.M33 + matrix.M43);
		}
		/// <summary>
		/// 変換してW=1に投影する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <returns></returns>
		public static Vector3 Transform(Vector3 position, Matrix matrix) {
			Vector3 result;
			Transform(ref position, ref matrix, out result);
			return result;
		}
	}

	public partial struct Vector4 {
		/// <summary>
		/// 変換する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <param name="result"></param>
		public static void Transform(ref Vector4 position, ref Matrix matrix, out Vector4 result) {
			result = new Vector4(
				position.X * matrix.M11 + position.Y * matrix.M21 + position.Z * matrix.M31 + matrix.M41,
				position.X * matrix.M12 + position.Y * matrix.M22 + position.Z * matrix.M32 + matrix.M42,
				position.X * matrix.M13 + position.Y * matrix.M23 + position.Z * matrix.M33 + matrix.M43,
				position.X * matrix.M14 + position.Y * matrix.M24 + position.Z * matrix.M34 + matrix.M44);
		}
		/// <summary>
		/// 変換する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <returns></returns>
		public static Vector4 Transform(Vector4 position, Matrix matrix) {
			Vector4 result;
			Transform(ref position, ref matrix, out result);
			return result;
		}
	}

}
